/**
 * @brief 一个不通过配置文件创建API的示例
 *
 * 演示功能：
 * 1. 不通过配置文件创建API实例；
 * 2. 通过setConfig配置API实例的参数；
 * 3. 通过getConfig读取API实例的参数并打印到屏幕，以便于检查参数值；
 * 4. 启动API，启动成功后，调用login接口登录柜台；
 * 5. 登录柜台成功后，打印登录用户的账户信息；
 * 6. 等待3秒后，调用logout接口登出柜台；
 */

#include <map>
#include "ExampleTrader.h"

class Example_04_Trader : public ExampleTrader {
public:
    Example_04_Trader() = default;

    ~Example_04_Trader() override {
        // release api.
        if (mApi) {
            mApi->stop();
            delete mApi;
            mApi = nullptr;
        }
    };

    void onStart(int errorCode, bool isFirstTime) override {
        ExampleTrader::onStart(errorCode, isFirstTime);

        printf("api start ok.\n");
    }

    void onStop(int reason) override {
        ExampleTrader::onStop(reason);

        printf("api stopped, reason: %d.\n", reason);
    }

    void onLogin(int errorCode, int exchangeCount) override {
        ExampleTrader::onLogin(errorCode, exchangeCount);

        if (errorCode != 0)
            printf("login failed, error code: %d.\n", errorCode);
        else
            printf("login success, exchange count=%d.\n", exchangeCount);
    }

    void onLogout(int errorCode) override {
        ExampleTrader::onLogout(errorCode);

        printf("logout success.\n");
    }

    void onReadyForTrading(const XTFAccount *account) override {
        ExampleTrader::onReadyForTrading(account);

        printf("ready for trading.\n");
    }

    void onLoadFinished(const XTFAccount *account) override {
        ExampleTrader::onLoadFinished(account);

        printf("load data finished.\n");

        printf("account: %s\n", account->accountID);
        printf("  preBalance: %.4f\n", account->preBalance);
        printf("  deposit: %.4f\n", account->deposit);
        printf("  withdraw: %.4f\n", account->withdraw);
        printf("  commission: %.4f\n", account->commission);
        printf("  frozenCommission: %.4f\n", account->frozenCommission);
        printf("  margin: %.4f\n", account->margin);
        printf("  frozenMargin: %.4f\n", account->frozenMargin);
        printf("  balance: %.4f\n", account->balance);
        printf("  available: %.4f\n", account->available);
        printf("  positionProfit: %.4f\n", account->positionProfit);
        printf("  closeProfit: %.4f\n", account->closeProfit);
        printf("  prePositionCount: %d\n", account->getPrePositionCount());
        printf("  postionCount: %d\n", account->getPositionCount());
        printf("  orderCount: %d\n", account->getOrderCount());
        printf("  tradeCount: %d\n", account->getTradeCount());
        printf("  cashInOutCount: %d\n", account->getCashInOutCount());
    }

    void printConfigs() {
        printf("api configs:\n");
        printf("  ACCOUNT_ID: %s\n", mApi->getConfig("ACCOUNT_ID"));
        printf("  ACCOUNT_PWD: %s\n", mApi->getConfig("ACCOUNT_PWD"));
        printf("  APP_ID: %s\n", mApi->getConfig("APP_ID"));
        printf("  AUTH_CODE: %s\n", mApi->getConfig("AUTH_CODE"));
        printf("  TRADE_SERVER_IP: %s\n", mApi->getConfig("TRADE_SERVER_IP"));
        printf("  TRADE_SERVER_PORT: %s\n", mApi->getConfig("TRADE_SERVER_PORT"));
        printf("  QUERY_SERVER_IP: %s\n", mApi->getConfig("QUERY_SERVER_IP"));
        printf("  QUERY_SERVER_PORT: %s\n", mApi->getConfig("QUERY_SERVER_PORT"));
    }

    void setConfigs() {
        mApi->setConfig("ACCOUNT_ID", "40034002_1");
        mApi->setConfig("ACCOUNT_PWD", "111111");
        mApi->setConfig("APP_ID", "ATP_ATPRelay_V2");
        mApi->setConfig("AUTH_CODE", "ZXACUHZSBABUB7CZ");
        mApi->setConfig("TRADE_SERVER_IP", "192.168.4.63");
        mApi->setConfig("TRADE_SERVER_PORT", "10000");
        mApi->setConfig("QUERY_SERVER_IP", "192.168.4.63");
        mApi->setConfig("QUERY_SERVER_PORT", "10086");
    }

    void start() {
        if (mApi) {
            printf("error: trader has been started.\n");
            return;
        }

        // 传递nullptr，可创建一个默认的API对象
        mApi = makeXTFApi(nullptr);
        if (mApi == nullptr) {
            printf("error: create xtf api failed, please check config: %s.\n", mConfigPath.c_str());
            exit(0);
        }

        // 打印默认的参数值
        printConfigs();

        // 设置参数值
        setConfigs();

        // 检查参数值是否设置成功
        printConfigs();

        printf("api starting..., config: %s.\n", mConfigPath.c_str());
        int ret = mApi->start(this);
        if (ret != 0) {
            printf("start failed, error code: %d\n", ret);
            exit(0);
        }
    }

    void stop() {
        if (!mApi) {
            printf("error: trader is not started.\n");
            return;
        }

        printf("api stopping...\n");
        int ret = mApi->stop();
        if (ret == 0) {
            // API停止操作是异步操作，需要等待一定时间，以防API对象回调时失效。
            // 4.1.664及更高版本不存在此问题，不需要增加延时。
            usleep(100000);

            delete mApi;
            mApi = nullptr;
        } else {
            printf("api stop failed, error code: %d\n", ret);
        }
    }

    void login() {
        if (!mApi) return;
        printf("api logging in...\n");
        int ret = mApi->login();
        if (ret != 0) {
            printf("api logging in failed, error code: %d\n", ret);
        }
    }

    void logout() {
        if (!mApi) return;
        printf("api logging out...\n");
        int ret = mApi->logout();
        if (ret != 0) {
            printf("api logging out failed, error code: %d\n", ret);
        }
    }
};

int main(int argc, const char *argv[]) {
    printf("api version: %s.\n", getXTFVersion());
    printf("start example 04.\n");

    Example_04_Trader trader;
    trader.start();
    while (!trader.isStarted())
        trader.wait(1, "wait for trader started");

    trader.login();
    while (!trader.isLoadFinished())
        trader.wait(1, "wait for data load finished");

    trader.wait(3, "wait for logout");

    trader.logout();
    while (!trader.isLoggedOut())
        trader.wait(1, "wait for trader logout");

    trader.stop();
    while (!trader.isStopped())
        trader.wait(1, "wait for trader stopped");
    return 0;
}
